package com.demo2;

import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: fzykd
 * Date: 2022-12-21
 * Time: 21:22
 */
//管理一个事物 先描述 在组织
class MyTask implements Comparable<MyTask>{
    //描述一个任务
    private Runnable runnable;
    //多级之后执行的事件
    private long time;

    //构造函数 构造任务
    public MyTask(Runnable runnable,long after){
        this.runnable = runnable;
        //举例 3秒后 是一个相对时间
        this.time = after + System.currentTimeMillis();
    }

    public long getTime(){
        return this.time;
    }

    public void run(){
        this.runnable.run();
    }

    //还有就是明确 阻塞队列的比较方式 原则上是一个堆比较
    public int compareTo(MyTask o){
        return (int) (this.time - o.time);
    }
}

class MyTimer{
    //任务在定时器中排队执行 要有一个数据结构来组织
    //线程安全的阻塞队列
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();

    //定时器中有一个布置任务的方法
    public void schedule(Runnable runnable,long time){
        MyTask task = new MyTask(runnable,time);
        queue.put(task);
        //不要忘了 有新的任务进来之后 提醒检查新的任务是否最先执行
        synchronized (locker){
            locker.notify();
        }
    }

    //锁对象
    Object locker = new Object();

    //在定时器的构造函数中要有一个线程不断的检查是否有时间到的 有时间到了的就执行 没有就在放回去
    public MyTimer(){
        Thread t = new Thread(()->{
            //取出来和现在的事件比较
            try {
                MyTask task = queue.take();
                long curTime = System.currentTimeMillis();
                if (task.getTime() > curTime){
                    //放回  为了防止忙等 设置一个等待时间
                    queue.put(task);
                    synchronized (locker){
                        locker.wait(task.getTime() - curTime);
                    }
                }
                //否则就执行
                task.run();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t.start();
    }

}

//实现一个自己版本的定时器
public class TestDemo4 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("自主实现定时器!");
            }
        },3000);
    }
}
